#!/usr/bin/env ts-node
/**
 * Blueprint对齐工具
 * 用于对齐Blueprint与方案文档字段，确保数据源优先级正确
 */

import * as fs from 'fs';
import * as path from 'path';

const getErrorMessage = (error: unknown): string => {
  if (error instanceof Error) {
    return error.message;
  }
  if (typeof error === 'string') {
    return error;
  }
  try {
    return JSON.stringify(error);
  } catch {
    return String(error);
  }
};

interface RequirementField {
  type: string;
  source: string;
  required: boolean;
  default?: any;
  description?: string;
}

interface BlueprintProp {
  name: string;
  type: string;
  default?: any;
  source?: string;
  alignmentSource?: string;
  missingInFigma?: boolean;
  addedFromFigma?: boolean;
  description?: string;
}

interface AlignmentResult {
  configurableProps: BlueprintProp[];
  conflicts: Array<{
    field: string;
    requirementType?: string;
    figmaType?: string;
    requirementName?: string;
    figmaName?: string;
    resolution: string;
  }>;
  alignmentSummary: {
    totalFields: number;
    fromRequirement: number;
    fromFigma: number;
    conflicts: number;
  };
}

class BlueprintAligner {
  private componentName: string;
  private workflowRoot: string;

  constructor(componentName: string) {
    this.componentName = componentName;
    this.workflowRoot = path.join(process.cwd(), this.componentName);
  }

  /**
   * 加载requirement字段定义
   */
  private loadRequirementFields(): Record<string, RequirementField> | null {
    const requirementPath = path.join(this.workflowRoot, 'phase0/requirement-fields.json');
    if (!fs.existsSync(requirementPath)) {
      console.warn('⚠️  No requirement-fields.json found, using Figma data only');
      return null;
    }

    const data = JSON.parse(fs.readFileSync(requirementPath, 'utf-8'));
    return data.fields || {};
  }

  /**
   * 加载Figma语义信息
   */
  private loadFigmaSemantics(): any {
    const semanticsPath = path.join(this.workflowRoot, 'phase1/figma-semantics.json');
    if (!fs.existsSync(semanticsPath)) {
      return { contentPanels: [], stylePanels: [], themeTokens: {}, resources: {} };
    }

    return JSON.parse(fs.readFileSync(semanticsPath, 'utf-8'));
  }

  /**
   * 加载原始Blueprint
   */
  private loadOriginalBlueprint(): any {
    const blueprintPath = path.join(this.workflowRoot, 'phase1/blueprint.json');
    if (!fs.existsSync(blueprintPath)) {
      throw new Error('Original blueprint.json not found');
    }

    return JSON.parse(fs.readFileSync(blueprintPath, 'utf-8'));
  }

  /**
   * 检测字段类型兼容性
   */
  private isTypeCompatible(requirementType: string, figmaType: string): boolean {
    const typeMap: Record<string, string[]> = {
      'string': ['string', 'text'],
      'number': ['number', 'int', 'float'],
      'boolean': ['boolean', 'bool'],
      'string[]': ['array', 'string[]', 'Array<string>'],
      'object': ['object', 'Object', 'any']
    };

    const reqNormalized = requirementType.toLowerCase();
    const figmaNormalized = figmaType.toLowerCase();

    if (reqNormalized === figmaNormalized) return true;

    const compatibleTypes = typeMap[reqNormalized] || [];
    return compatibleTypes.includes(figmaNormalized);
  }

  /**
   * 执行Blueprint对齐
   */
  async alignBlueprint(): Promise<AlignmentResult> {
    console.log(`📐 Aligning Blueprint for ${this.componentName}...`);

    const requirementFields = this.loadRequirementFields();
    const figmaSemantics = this.loadFigmaSemantics();
    const originalBlueprint = this.loadOriginalBlueprint();

    const alignedProps: BlueprintProp[] = [];
    const conflicts: AlignmentResult['conflicts'] = [];
    const processedFields = new Set<string>();

    // Step 1: 优先处理方案文档字段
    if (requirementFields) {
      console.log('  ✓ Processing requirement fields...');

      for (const [fieldName, fieldDef] of Object.entries(requirementFields)) {
        processedFields.add(fieldName);

        // 查找Figma中对应字段
        const figmaField = originalBlueprint.configurableProps?.find(
          (p: any) => p.name === fieldName || p.name === this.toSnakeCase(fieldName)
        );

        if (figmaField) {
          // 字段存在，检查类型一致性
          if (!this.isTypeCompatible(fieldDef.type, figmaField.type)) {
            conflicts.push({
              field: fieldName,
              requirementType: fieldDef.type,
              figmaType: figmaField.type,
              resolution: 'use requirement type'
            });
          }

          alignedProps.push({
            name: fieldName,
            type: fieldDef.type, // 使用requirement的类型
            default: fieldDef.default || figmaField.default,
            source: 'requirement',
            alignmentSource: 'both',
            description: fieldDef.description
          });
        } else {
          // Figma中缺失此字段
          alignedProps.push({
            name: fieldName,
            type: fieldDef.type,
            default: fieldDef.default,
            source: 'requirement',
            alignmentSource: 'requirement_only',
            missingInFigma: true,
            description: fieldDef.description
          });

          console.log(`  ⚠️  Field "${fieldName}" missing in Figma, added from requirement`);
        }
      }
    }

    // Step 2: 处理Figma独有字段
    if (originalBlueprint.configurableProps) {
      console.log('  ✓ Processing Figma-only fields...');

      for (const figmaField of originalBlueprint.configurableProps) {
        if (!processedFields.has(figmaField.name)) {
          processedFields.add(figmaField.name);

          // 检查是否是命名差异
          const similarRequirementField = this.findSimilarField(figmaField.name, requirementFields);
          if (similarRequirementField) {
            conflicts.push({
              field: figmaField.name,
              requirementName: similarRequirementField,
              figmaName: figmaField.name,
              resolution: `use requirement naming: ${similarRequirementField}`
            });
            continue;
          }

          // 添加Figma独有字段
          alignedProps.push({
            name: figmaField.name,
            type: figmaField.type,
            default: figmaField.default,
            source: 'figma',
            alignmentSource: 'figma_only',
            addedFromFigma: true
          });
        }
      }
    }

    // Step 3: 补充面板推断的字段
    console.log('  ✓ Processing panel-inferred fields...');

    const panelFields = [...figmaSemantics.contentPanels, ...figmaSemantics.stylePanels];
    for (const panelField of panelFields) {
      if (!processedFields.has(panelField.name)) {
        alignedProps.push({
          name: panelField.name,
          type: panelField.type,
          default: panelField.default,
          source: 'figmaPanel',
          alignmentSource: 'figma_panel'
        });
        processedFields.add(panelField.name);
      }
    }

    // 生成对齐摘要
    const alignmentSummary = {
      totalFields: alignedProps.length,
      fromRequirement: alignedProps.filter(p => p.alignmentSource?.includes('requirement')).length,
      fromFigma: alignedProps.filter(p => p.alignmentSource?.includes('figma')).length,
      conflicts: conflicts.length
    };

    const result: AlignmentResult = {
      configurableProps: alignedProps,
      conflicts,
      alignmentSummary
    };

    // 保存对齐后的blueprint
    await this.saveAlignedBlueprint(result);

    this.printSummary(result);

    return result;
  }

  /**
   * 转换为snake_case
   */
  private toSnakeCase(str: string): string {
    return str.replace(/([A-Z])/g, '_$1').toLowerCase().replace(/^_/, '');
  }

  /**
   * 查找相似字段名
   */
  private findSimilarField(figmaName: string, requirementFields: Record<string, RequirementField> | null): string | null {
    if (!requirementFields) return null;

    const figmaLower = figmaName.toLowerCase().replace(/_/g, '');

    for (const reqField in requirementFields) {
      const reqLower = reqField.toLowerCase().replace(/_/g, '');
      if (figmaLower === reqLower) {
        return reqField;
      }
    }

    return null;
  }

  /**
   * 保存对齐后的Blueprint
   */
  private async saveAlignedBlueprint(result: AlignmentResult): Promise<void> {
    const originalBlueprint = this.loadOriginalBlueprint();

    const alignedBlueprint = {
      ...originalBlueprint,
      configurableProps: result.configurableProps,
      alignmentSummary: result.alignmentSummary,
      conflicts: result.conflicts,
      _metadata: {
        aligned: true,
        alignedAt: new Date().toISOString(),
        version: '2.0'
      }
    };

    const outputPath = path.join(this.workflowRoot, 'phase1/blueprint-aligned.json');
    fs.writeFileSync(outputPath, JSON.stringify(alignedBlueprint, null, 2));

    console.log(`\n✅ Aligned blueprint saved to: ${outputPath}`);
  }

  /**
   * 打印对齐摘要
   */
  private printSummary(result: AlignmentResult): void {
    console.log('\n' + '='.repeat(60));
    console.log('Blueprint Alignment Summary');
    console.log('='.repeat(60));

    console.log(`\nTotal Fields: ${result.alignmentSummary.totalFields}`);
    console.log(`  - From Requirement: ${result.alignmentSummary.fromRequirement}`);
    console.log(`  - From Figma: ${result.alignmentSummary.fromFigma}`);
    console.log(`  - Conflicts: ${result.alignmentSummary.conflicts}`);

    if (result.conflicts.length > 0) {
      console.log('\n⚠️  Conflicts Detected:');
      for (const conflict of result.conflicts) {
        console.log(`  - ${conflict.field}: ${conflict.resolution}`);
        if (conflict.requirementType && conflict.figmaType) {
          console.log(`    Type mismatch: ${conflict.requirementType} vs ${conflict.figmaType}`);
        }
        if (conflict.requirementName && conflict.figmaName) {
          console.log(`    Name mismatch: ${conflict.requirementName} vs ${conflict.figmaName}`);
        }
      }
    }

    const missingInFigma = result.configurableProps.filter(p => p.missingInFigma);
    if (missingInFigma.length > 0) {
      console.log('\n📝 Fields added from requirement (missing in Figma):');
      for (const field of missingInFigma) {
        console.log(`  - ${field.name} (${field.type})`);
      }
    }

    const addedFromFigma = result.configurableProps.filter(p => p.addedFromFigma);
    if (addedFromFigma.length > 0) {
      console.log('\n🎨 Fields added from Figma (not in requirement):');
      for (const field of addedFromFigma) {
        console.log(`  - ${field.name} (${field.type})`);
      }
    }

    console.log('\n' + '='.repeat(60));
  }

  /**
   * 验证对齐结果
   */
  async validateAlignment(): Promise<boolean> {
    const alignedPath = path.join(this.workflowRoot, 'phase1/blueprint-aligned.json');

    if (!fs.existsSync(alignedPath)) {
      console.error('❌ No aligned blueprint found');
      return false;
    }

    const aligned = JSON.parse(fs.readFileSync(alignedPath, 'utf-8'));

    // 验证必需字段
    const requirementFields = this.loadRequirementFields();
    if (requirementFields) {
      const missingRequired: string[] = [];

      for (const [fieldName, fieldDef] of Object.entries(requirementFields)) {
        if (fieldDef.required) {
          const found = aligned.configurableProps?.find((p: any) => p.name === fieldName);
          if (!found) {
            missingRequired.push(fieldName);
          }
        }
      }

      if (missingRequired.length > 0) {
        console.error('❌ Missing required fields:', missingRequired);
        return false;
      }
    }

    console.log('✅ Blueprint alignment validation passed');
    return true;
  }
}

// CLI执行
if (require.main === module) {
  const args = process.argv.slice(2);
  const componentName = args[0];
  const action = args[1] || 'align';

  if (!componentName) {
    console.error('Usage: ts-node blueprint-aligner.ts <ComponentName> [align|validate]');
    process.exit(1);
  }

  const aligner = new BlueprintAligner(componentName);

  (async () => {
    try {
      switch (action) {
        case 'align':
          await aligner.alignBlueprint();
          break;
        case 'validate':
          const isValid = await aligner.validateAlignment();
          process.exit(isValid ? 0 : 1);
          break;
        default:
          console.error(`Unknown action: ${action}`);
          process.exit(1);
      }
    } catch (error) {
      console.error('❌ Alignment failed:', getErrorMessage(error));
      process.exit(1);
    }
  })();
}

export default BlueprintAligner;